﻿using System.Collections.Generic;
using HP48CSharp.Interfaces;
using HP48CSharp.Entities;
using System.Linq;
using System;
using HP48CSharp.Core;

namespace HP48CSharp
{
    public class Heap : IHeap
    {
        #region Private Members
        private object[] elements;
        private IFilter filter;
        private CSharpCompilerCore cSharpCompiler;
        #endregion

        public int Count { get; private set; }

        public Heap()
        {
            elements = new object[Int16.MaxValue];
            filter = new Filter();
            filter.Tokens = new TokenOperators();
            
            Count = 0;
        }

        public void Add(object o)
        {
            var value = o;
            if (value.GetType().ToString() == "System.Char")
            {
                if (filter.Contains(value))
                {
                    cSharpCompiler = new OperationCompiler(this, (char)o);
                    value = cSharpCompiler.CompileExecutable();
                    Pop();
                    Pop();
                }
            }
            AddInternal(value);

        }

        private void AddInternal(object o)
        {
            elements.SetValue(o, Count);
            Count += 1;
        }


        /// <summary>
        /// Return an element of the heap
        /// </summary>
        /// <param name="index">position's number of the element</param>
        /// <returns></returns>
        public object Get(int index)
        {
            return elements.GetValue(index);
        }

        public void Pop()
        {
            Heap elements_clone = new Heap();

            int counter = 0;
            int max = Count;
            while (counter <= max - 2)
            {
                elements_clone.Add(elements.GetValue(counter));
                counter++;
            }
            Count--;
            elements = elements_clone.elements;

        }



        #region IEnumerable<object> Members

        public IEnumerator<object> GetEnumerator()
        {
            int counter = 0;
            while (counter++ <= Count)
            {
                yield return elements.GetValue(counter);
            }
        }

        #endregion


        public void Swap()
        {
            object o0 = elements.GetValue(Count - 1);
            object o1 = elements.GetValue(Count - 2);

            elements.SetValue(o0, Count - 2);
            elements.SetValue(o1, Count - 1);
        }

    }
}
